import {
  Shader,
  ShaderData,
  ShaderProperty,
  ShaderPool,
  ShaderProgram,
  ShaderProgramPool,
  ShaderMacro,
  ShaderMacroCollection,
  ShaderDataGroup,
  ShaderLib
} from "@nirvana/shaders";
import { Color, Vector3 } from "@nirvana/math";

import { WebGLCanvas } from "@nirvana/canvas";
import { Data, Mesh, DataElement, Geometry, SimpleMaterial, Camera } from "@nirvana/core";

// 使用使用 Canvas
let canvas = document.getElementById("engine-nirvana");
const webCanvas = new WebGLCanvas(canvas, {});
const engine = webCanvas.engine;
const gl = engine.gl;

// const simple = Shader.find("simple");
// const mt = new ShaderMaterial("mesh mt", simple);
// const shaderData = mt.shaderData;
// shaderData.enableMacro("O3_HAS_VERTEXCOLOR");
// shaderData.enableMacro("O3_HAS_NORMAL");

const mt = new SimpleMaterial("s", {
  color: true,
  normal: true
});

// 点数
var triangles = 160000;

var positions: number[] = [];
// 点的法向量
var normals: number[] = [];
var colors: number[] = [];

var color = new Color();

// 正方体, 长宽高都为800
var n = 800,
  n2 = n / 2;
// 三角形三个点点在正方体内, 这个正方体长宽高都为12
var d = 12,
  d2 = d / 2;

// abc, 三个顶点位置
var pA = new Vector3();
var pB = new Vector3();
var pC = new Vector3();
// c点到b点的方向向量
var cb = new Vector3();
// a点到b点的方向向量
var ab = new Vector3();

for (let i = 0; i < triangles; i++) {
  // positions

  var x = Math.random() * n - n2;
  var y = Math.random() * n - n2;
  var z = Math.random() * n - n2;

  var ax: number = x + Math.random() * d - d2;
  var ay: number = y + Math.random() * d - d2;
  var az: number = z + Math.random() * d - d2;

  var bx: number = x + Math.random() * d - d2;
  var by: number = y + Math.random() * d - d2;
  var bz: number = z + Math.random() * d - d2;

  var cx = x + Math.random() * d - d2;
  var cy = y + Math.random() * d - d2;
  var cz = z + Math.random() * d - d2;

  // 添加一个三角形的3个顶点, 每个顶点有xyz三个数据
  positions.push(ax, ay, az);
  positions.push(bx, by, bz);
  positions.push(cx, cy, cz);

  // 求法向量, 首先设置三角形的三个顶点
  pA.set(ax, ay, az);
  pB.set(bx, by, bz);
  pC.set(cx, cy, cz);
  // 求出两个方向向量
  cb = pC.clone().sub(pB);
  // cb.sub(pC, pB);
  ab = pA.clone().sub(pB);
  // ab.sub(pA, pB);
  // 叉积, 求法向量
  cb.cross(ab);
  // 单位化这个法向量
  cb.normalize();

  var nx = cb.x;
  var ny = cb.y;
  var nz = cb.z;
  // 添加法向量到法向量数组中
  // 三角形的三个顶点的法向量相同, 因此复制三份
  normals.push(nx, ny, nz);
  normals.push(nx, ny, nz);
  normals.push(nx, ny, nz);

  // colors

  var vx = x / n + 0.5;
  var vy = y / n + 0.5;
  var vz = z / n + 0.5;

  color.set(vx, vy, vz);

  colors.push(color.r, color.g, color.b);
  colors.push(color.r, color.g, color.b);
  colors.push(color.r, color.g, color.b);
}

const gem = new Geometry();

gem.addData(new Data(new Float32Array(positions), [new DataElement("POSITION", 3)]));
gem.addData(new Data(new Float32Array(normals), [new DataElement("NORMAL", 3, gl.FLOAT, false, 0, 0)]));
gem.addData(new Data(new Float32Array(colors), [new DataElement("COLOR_0", 3, gl.FLOAT, false, 0, 0)]));

const entity = new Mesh(gem, mt);

const scene = engine.sceneManager.createScene("root");
scene.addEntity(entity);
const camera = new Camera(engine);
scene.addCamera(camera);
camera.transform.setPosition(new Vector3(0, 0, 10));
// entity.setDrawMode("lineloop");
entity.transform.rotate(new Vector3(0, 0, 60));
//
// entity.add(entity1);
// entity.add(entity2);
// entity.add(entity3);
// entity1.transform.scale(new Vector3(0.8, 0.8, 0.8));
// entity2.transform.scale(new Vector3(0.5, 0.5, 0.5));
entity.transform.scale(new Vector3(0.005, 0.005, 0.005));

engine.update = () => {
  // // console.log('--');
  // gl.clearColor(0.0, 0.0, 0.0, 1.0);
  // // 用上面指定的颜色清除缓冲区
  // gl.clear(gl.COLOR_BUFFER_BIT);
  // entity.transform.translate(new Vector3(0, 0, 0.01));
  // entity1.transform.translate(new Vector3(0.01, 0.02, 0));
  // entity2.transform.translate(new Vector3(-0.01, 0.02, 0));
  // entity3.transform.translate(new Vector3(0.01, -0.02, 0));
  // let rand = 5 * Math.random();
  // entity.transform.rotate(new Vector3(0, 0, rand));
  // entity.transform.rotate(new Vector3(0, 0, 1));
  // entity.transform.rotate(new Vector3(0, 0, 2));
  // entity2.transform.rotate(new Vector3(0, 0, 4));
  // entity3.transform.rotate(new Vector3(0, 0, 6));
  // entity.transform.scale(new Vector3(rand, rand, rand));
};
